use core::ops::Bound;
use core::ops::Range;
use core::ops::RangeBounds;
use core::ops::RangeFrom;
use core::ops::RangeFull;
use core::ops::RangeInclusive;
use core::ops::RangeTo;
use core::ops::RangeToInclusive;

/// 提供类似于 SliceIndex 的使用方式。
pub trait BitIndex {
    fn low(&self) -> Bound<&u32>;
    fn upper(&self) -> Bound<&u32>;
}

impl BitIndex for RangeInclusive<u32> {
    #[inline]
    fn upper(&self) -> Bound<&u32> {
        self.end_bound()
    }
    #[inline]
    fn low(&self) -> Bound<&u32> {
        self.start_bound()
    }
}

impl BitIndex for RangeFull {
    #[inline]
    fn low(&self) -> Bound<&u32> {
        Bound::Included(&0)
    }

    #[inline]
    fn upper(&self) -> Bound<&u32> {
        Bound::Unbounded
    }
}

impl BitIndex for RangeFrom<u32> {
    #[inline]
    fn low(&self) -> Bound<&u32> {
        self.start_bound()
    }

    #[inline]
    fn upper(&self) -> Bound<&u32> {
        Bound::Unbounded
    }
}

impl BitIndex for RangeTo<u32> {
    #[inline]
    fn low(&self) -> Bound<&u32> {
        Bound::Included(&0)
    }

    #[inline]
    fn upper(&self) -> Bound<&u32> {
        self.end_bound()
    }
}

impl BitIndex for Range<u32> {
    #[inline]
    fn upper(&self) -> Bound<&u32> {
        self.end_bound()
    }

    #[inline]
    fn low(&self) -> Bound<&u32> {
        self.start_bound()
    }
}

impl BitIndex for u32 {
    #[inline]
    fn upper(&self) -> Bound<&u32> {
        Bound::Included(self)
    }

    #[inline]
    fn low(&self) -> Bound<&u32> {
        Bound::Included(self)
    }
}

impl BitIndex for RangeToInclusive<u32> {
    #[inline]
    fn low(&self) -> Bound<&u32> {
        Bound::Included(&0)
    }

    #[inline]
    fn upper(&self) -> Bound<&u32> {
        self.end_bound()
    }
}